package com.usefullc.blog.service;
import java.util.Date;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.usefullc.blog.domain.*;
import com.usefullc.blog.enums.ArticleStatusEnum;
import com.usefullc.blog.param.ArticleParam;
import com.usefullc.blog.query.*;
import com.usefullc.common.enums.YesNoEnum;
import com.usefullc.common.user.OnlineUser;
import com.usefullc.common.user.OnlineUserManager;
import com.usefullc.common.util.BeanUtils;
import com.usefullc.blog.mapper.ArticleMapper;
import com.usefullc.blog.vo.ArticleVo;
import com.usefullc.common.util.RequestUtils;
import com.usefullc.system.entity.Pager;
import com.usefullc.system.service.AbstractBizService;
import com.usefullc.system.validator.UsefulPropertyVerify;
import com.usefullc.system.vo.TreeVo;
import com.usefullc.user.domain.User;
import com.usefullc.user.service.UserService;
import com.usefullc.user.service.component.UserManager;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 文章服务类
 * @author: 星空
 * @date: 20220628
 */
@Service
public class ArticleService extends AbstractBizService<ArticleMapper, Article, ArticleQuery> {


    @Autowired
    private CategoryService categoryService;

    @Autowired
    private UserService userService;

    @Autowired
    private ArticleReadService articleReadService;

    @Autowired
    private ReplyService replyService;

    @Autowired
    private ReplyLikeService replyLikeService;

    @Autowired
    private ArticleLikeService articleLikeService;

    @Autowired
    private ArticleShareService articleShareService;

    @Autowired
    private TagService tagService;

    @Override
    protected QueryWrapper<Article> getQueryWrapper(ArticleQuery query) {
        QueryWrapper<Article> queryWrapper = super.getQueryWrapper(query);
        return queryWrapper;
    }

    public Pager<ArticleVo> findVoByPage(ArticleQuery query){
        Pager<Article> page = this.findByPage(query);
        Pager<ArticleVo> newPage = new Pager<>(page);
        List<Article> dataList = page.getDataList();
        List<ArticleVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (Article article : dataList) {
            ArticleVo articleVo = BeanUtils.beanCopy(article, ArticleVo.class);

            //标签
            List<Tag> tagList = tagService.getBaseMapper().findByArticleId(article.getId());
            if (CollectionUtils.isNotEmpty(tagList)) {

                List<String> tags = tagList.stream().map(data -> data.getName()).collect(Collectors.toList());
                articleVo.setTags(tags);
            }

            newDataList.add(articleVo);
        }
        return newPage;
    }

    public Pager<ArticleVo> findCmsVoByPage(ArticleQuery query){
        Pager<Article> page = this.findByPage(query);
        Pager<ArticleVo> newPage = new Pager<>(page);
        List<Article> dataList = page.getDataList();
        List<ArticleVo> newDataList = new ArrayList<>();
        newPage.setDataList(newDataList);
        for (Article article : dataList) {
            ArticleVo articleVo = wrapperCmsArticle(article);
            newDataList.add(articleVo);
        }
        return newPage;
    }

    public List<ArticleVo> findCmsList(ArticleQuery query){
        List<Article> dataList = this.findAll(query);
        List<ArticleVo> newDataList = new ArrayList<>();
        for (Article article : dataList) {
            ArticleVo articleVo = wrapperCmsArticle(article);
            newDataList.add(articleVo);
        }
        return newDataList;
    }

    public Pager<ArticleVo> findCmsPageVoByTag(TagQuery query){
        long total = this.baseMapper.findCountByTagId(query.getId());
        Pager<ArticleVo> pager = new Pager<>(query.getPageIndex(),query.getPageSize(),total);
        if(total == 0){
            return pager;
        }
        List<Article> dataList = this.baseMapper.findByTagId(query.getId(),pager);
        List<ArticleVo> newDataList = new ArrayList<>();
        for (Article article : dataList) {
            ArticleVo articleVo = wrapperCmsArticle(article);
            newDataList.add(articleVo);
        }
        pager.setDataList(newDataList);
        return pager;
    }

    public ArticleVo wrapperCmsArticle(Article article){
        if(article == null){
            return null;
        }
        ArticleVo articleVo = BeanUtils.beanCopy(article, ArticleVo.class);
        //用户
        Long userId = article.getUserId();

        User user = userService.findById(userId);
        String author = "匿名";
        String avator = "";
        if(user != null){
            author = user.getNickname();
            avator = user.getAvatar();
        }
        articleVo.setAuthor(author);
        articleVo.setAvatar(avator);

        //类目
        Category category = categoryService.findById(article.getCategoryId());
        articleVo.setCategory(category);

        return articleVo;

    }


    public List<TreeVo> listTree(ArticleQuery query) {
        //获取类目
        List<TreeVo> categoryTreeList = categoryService.listTree(new CategoryQuery());


        //每个节点添加文章
        List<Article> articleList = this.findAll(query);
        Map<Long, List<Article>> articleMap = articleList.stream().collect(Collectors.groupingBy(data -> data.getCategoryId()));

        List<TreeVo> newTreeList = new ArrayList<>();
        wrapperLitTree(categoryTreeList,newTreeList,articleMap);

        return newTreeList;
    }

    private void wrapperLitTree(List<TreeVo> categoryTreeList,List<TreeVo> resultTreeList,Map<Long, List<Article>> articleMap){
        for (TreeVo treeVo : categoryTreeList) {
            String key = treeVo.getKey();

            TreeVo newTreeVo = new TreeVo();
            newTreeVo.setTitle("[类目]"+treeVo.getTitle());
            newTreeVo.setKey("c"+treeVo.getKey());
            newTreeVo.setValue("c"+treeVo.getValue());
            resultTreeList.add(newTreeVo);

            List<TreeVo> newChildren = new ArrayList<>();
            newTreeVo.setChildren(newChildren);
            List<TreeVo> categoryTreeChildren = treeVo.getChildren();

            if (CollectionUtils.isNotEmpty(categoryTreeChildren)) {  //有子类目，再递归
                wrapperLitTree(categoryTreeChildren,newChildren,articleMap);
            }

            //每个类目去添加文章集合
            List<Article> childArticleList = articleMap.get(Long.valueOf(key));
            if (CollectionUtils.isNotEmpty(childArticleList)) {
                for (Article article : childArticleList) {
                    TreeVo childTreeVo = new TreeVo();
                    newChildren.add(childTreeVo);
                    childTreeVo.setTitle("[文章]"+article.getTitle());
                    childTreeVo.setValue("a"+article.getId().toString());
                    childTreeVo.setKey("a"+article.getId().toString());
                }
            }
        }

    }

    @Transactional
    public boolean saveArticle(ArticleParam param){
        boolean result;
        Article entity;
        if(param.getId() == null){
            entity = BeanUtils.beanCopy(param, Article.class);
            if(entity.getUserId() == null){
                entity.setUserId(UserManager.getLoginUser().getId());
            }
            entity.setStatus(ArticleStatusEnum.DRAFT.getCode());
            entity.setContribution(YesNoEnum.NO.getCode());
            entity.setLikeNum(0);
            entity.setReplyNum(0);
            entity.setReadNum(0);
            entity.setShareNum(0);
            this.save(entity);
            result = this.update(entity);
        }else{
            entity = this.findById(param.getId());
            BeanUtils.beanCopy(param, entity);
            result = this.update(entity);
        }

        //标签处理
        tagService.getBaseMapper().deleteArticleTagByArticleId(param.getId());

        List<String> tags = param.getTags();
        for (String tagName : tags) {
            Tag tag = tagService.findByTagName(tagName);
            if(tag == null){
                tag = new Tag();
                tag.setName(tagName);
                tag.setDescription(tagName);
            }
            tagService.save(tag);
            tagService.getBaseMapper().insertArticleTag(entity.getId(),tag.getId());
        }
        return result;
    }

    @Override
    public boolean save(Article entity) {
        super.save(entity);
        return super.update(entity);
    }

    @Override
    public boolean update(Article entity) {
        //设置url
        entity.setUrl("/cmsBlog/article/"+entity.getId()+".html");
        return super.update(entity);
    }

    public boolean doRead(Long articleId){
        ArticleRead articleRead = new ArticleRead();
        articleRead.setArticleId(articleId);
        HttpServletRequest request = RequestUtils.getRequest();
        String ip = RequestUtils.getClientIpAddr(request);
        OnlineUser loginUser = OnlineUserManager.getLoginUser();
        if(loginUser != null){
            articleRead.setUserId(loginUser.getUserId());
        }
        articleRead.setIp(ip);
        return articleReadService.save(articleRead);
    }

    public void updateActionNum(){
        //获取所有文章
        ArticleQuery articleQuery = new ArticleQuery();
        articleQuery.setStatus(ArticleStatusEnum.RELEASED.getCode());
        List<Article> dataList = this.findAll(articleQuery);
        for (Article article : dataList) {
            Long articleId = article.getId();
            //获取文章的阅读数
            ArticleReadQuery articleReadQuery = new ArticleReadQuery();
            articleReadQuery.setArticleId(article.getId());
            long readCount = articleReadService.count(articleReadQuery);

            //获取点赞数
            ArticleLikeQuery articleLikeQuery = new ArticleLikeQuery();
            articleLikeQuery.setArticleId(article.getId());
            articleLikeQuery.setStatus(YesNoEnum.YES.getCode());
            long likeCount = articleLikeService.count(articleLikeQuery);

            //回复数量
            ReplyQuery replyQuery = new ReplyQuery();
            replyQuery.setArticleId(article.getId());
            long replyCount = replyService.count(replyQuery);

            //分享数量
            ArticleShareQuery articleShareQuery = new ArticleShareQuery();
            articleShareQuery.setArticleId(article.getId());
            long shareCount = articleShareService.count(articleShareQuery);


            //修改
            this.baseMapper.updateActionNum(articleId,readCount,likeCount,replyCount,shareCount);


        }
    }
}
